{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "cedf868076a2"
   },
   "source": [
    "##### Copyright 2020 The Cirq Developers"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {
    "cellView": "form",
    "id": "906e07f6e562"
   },
   "outputs": [],
   "source": [
    "# @title Licensed under the Apache License, Version 2.0 (the \"License\");\n",
    "# you may not use this file except in compliance with the License.\n",
    "# You may obtain a copy of the License at\n",
    "#\n",
    "# https://www.apache.org/licenses/LICENSE-2.0\n",
    "#\n",
    "# Unless required by applicable law or agreed to in writing, software\n",
    "# distributed under the License is distributed on an \"AS IS\" BASIS,\n",
    "# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n",
    "# See the License for the specific language governing permissions and\n",
    "# limitations under the License."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "bf6694967996"
   },
   "source": [
    "# Quantum simulation of electronic structure"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "d96dfab4145b"
   },
   "source": [
    "<table class=\"tfo-notebook-buttons\" align=\"left\">\n",
    "  <td>\n",
    "    <a target=\"_blank\" href=\"https://quantumai.google/openfermion/tutorials/intro_workshop_exercises\"><img src=\"https://quantumai.google/site-assets/images/buttons/quantumai_logo_1x.png\" />View on QuantumAI</a>\n",
    "  </td>\n",
    "  <td>\n",
    "    <a target=\"_blank\" href=\"https://colab.research.google.com/github/quantumlib/OpenFermion/blob/master/docs/tutorials/intro_workshop_exercises.ipynb\"><img src=\"https://quantumai.google/site-assets/images/buttons/colab_logo_1x.png\" />Run in Google Colab</a>\n",
    "  </td>\n",
    "  <td>\n",
    "    <a target=\"_blank\" href=\"https://github.com/quantumlib/OpenFermion/blob/master/docs/tutorials/intro_workshop_exercises.ipynb\"><img src=\"https://quantumai.google/site-assets/images/buttons/github_logo_1x.png\" />View source on GitHub</a>\n",
    "  </td>\n",
    "  <td>\n",
    "    <a href=\"https://storage.googleapis.com/tensorflow_docs/OpenFermion/docs/tutorials/intro_workshop_exercises.ipynb\"><img src=\"https://quantumai.google/site-assets/images/buttons/download_icon_1x.png\" />Download notebook</a>\n",
    "  </td>\n",
    "</table>"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "c3dd9da6211f"
   },
   "source": [
    "The quantum simulation of electronic structure is one of the most promising applications of quantum computers. It has potential applications to materials and drug design. This tutorial provides an introduction to OpenFermion, a library for obtaining and manipulating representations of fermionic and qubit Hamiltonians as well as compiling quantum simulation circuits in Cirq."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {
    "id": "zeDOA0lc6YyI"
   },
   "outputs": [],
   "source": [
    "try:\n",
    "    import openfermion as of\n",
    "    import openfermionpyscf as ofpyscf\n",
    "except ImportError:\n",
    "    print(\"Installing OpenFermion and OpenFermion-PySCF...\")\n",
    "    !pip install openfermion openfermionpyscf --quiet"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {
    "id": "d1ed5395e9f5"
   },
   "outputs": [],
   "source": [
    "import numpy as np\n",
    "from scipy.sparse import linalg\n",
    "\n",
    "import cirq\n",
    "import openfermion as of\n",
    "import openfermionpyscf as ofpyscf"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "GzfsOoPI5sHP"
   },
   "source": [
    "## Background\n",
    "\n",
    "A system of $N$ fermionic modes is\n",
    "described by a set of fermionic *annihilation operators*\n",
    "$\\{a_p\\}_{p=0}^{N-1}$ satisfying the *canonical anticommutation relations*\n",
    "$$\\begin{aligned}\n",
    "    \\{a_p, a_q\\} &= 0, \\\\\n",
    "    \\{a_p, a^\\dagger_q\\} &= \\delta_{pq},\n",
    "  \\end{aligned}$$ where $\\{A, B\\} := AB + BA$. The adjoint\n",
    "$a^\\dagger_p$ of an annihilation operator $a_p$ is called a *creation\n",
    "operator*, and we refer to creation and annihilation operators as\n",
    "fermionic *ladder operators*.\n",
    "    \n",
    "The canonical anticommutation relations impose a number of consequences on the structure of the vector space on which the ladder operators act; see [Michael Nielsen's notes](http://michaelnielsen.org/blog/archive/notes/fermions_and_jordan_wigner.pdf) for a good discussion.\n",
    "\n",
    "The electronic structure Hamiltonian is commonly written in the form\n",
    "$$\n",
    "\\sum_{pq} T_{pq} a_p^\\dagger a_q + \\sum_{pqrs} V_{pqrs} a_p^\\dagger a_q^\\dagger a_r a_s\n",
    "$$\n",
    "where the $T_{pq}$ and $V_{pqrs}$ are coefficients which depend on the physical system being described. We are interested in calculating the lowest eigenvalue of the Hamiltonian. This eigenvalue is also called the ground state energy.\n",
    "\n",
    "\n",
    "## FermionOperator and QubitOperator\n",
    "\n",
    "### `openfermion.FermionOperator`\n",
    "\n",
    "- Stores a weighted sum (linear combination) of fermionic terms\n",
    "- A fermionic term is a product of ladder operators\n",
    "- Examples of things that can be represented by `FermionOperator`:\n",
    "$$\n",
    "\\begin{align}\n",
    "& a_1 \\nonumber \\\\\n",
    "& 1.7 a^\\dagger_3 \\nonumber \\\\\n",
    "&-1.7 \\, a^\\dagger_3 a_1 \\nonumber \\\\\n",
    "&(1 + 2i) \\, a^\\dagger_4 a^\\dagger_3 a_9 a_1 \\nonumber \\\\\n",
    "&(1 + 2i) \\, a^\\dagger_4 a^\\dagger_3 a_9 a_1 - 1.7 \\, a^\\dagger_3 a_1 \\nonumber\n",
    "\\end{align}\n",
    "$$\n",
    "\n",
    "- A fermionic term is internally represented as a tuple of tuples\n",
    "- Each inner tuple represents a single ladder operator as (index, action)\n",
    "- Examples of fermionic terms:\n",
    "$$\n",
    "\\begin{align}\n",
    "I & \\mapsto () \\nonumber \\\\\n",
    "a_1 & \\mapsto ((1, 0),) \\nonumber \\\\\n",
    "a^\\dagger_3 & \\mapsto ((3, 1),) \\nonumber \\\\\n",
    "a^\\dagger_3 a_1 & \\mapsto ((3, 1), (1, 0)) \\nonumber \\\\\n",
    "a^\\dagger_4 a^\\dagger_3 a_9 a_1 & \\mapsto ((4, 1), (3, 1), (9, 0), (1, 0)) \\nonumber\n",
    "\\end{align}\n",
    "$$\n",
    "\n",
    "- `FermionOperator` is a sum of terms, represented as a dictionary from term to coefficient"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {
    "id": "u1J3mO4r5sHR"
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "{((4, 1), (3, 1), (9, 0), (1, 0)): (1+2j), ((3, 1), (1, 0)): -1.7}\n"
     ]
    }
   ],
   "source": [
    "op = of.FermionOperator(((4, 1), (3, 1), (9, 0), (1, 0)), 1 + 2j) + of.FermionOperator(\n",
    "    ((3, 1), (1, 0)), -1.7\n",
    ")\n",
    "\n",
    "print(op.terms)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "6gMYqNFi5sHV"
   },
   "source": [
    "Alternative notation, useful when playing around:\n",
    "\n",
    "$$\n",
    "\\begin{align}\n",
    "I & \\mapsto \\textrm{\"\"} \\nonumber \\\\\n",
    "a_1 & \\mapsto \\textrm{\"1\"} \\nonumber \\\\\n",
    "a^\\dagger_3 & \\mapsto \\textrm{\"3^\"} \\nonumber \\\\\n",
    "a^\\dagger_3 a_1 & \\mapsto \\textrm{\"3^}\\;\\textrm{1\"} \\nonumber \\\\\n",
    "a^\\dagger_4 a^\\dagger_3 a_9 a_1 & \\mapsto \\textrm{\"4^}\\;\\textrm{3^}\\;\\textrm{9}\\;\\textrm{1\"} \\nonumber\n",
    "\\end{align}\n",
    "$$"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {
    "id": "w55QckU25sHW"
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "{((4, 1), (3, 1), (9, 0), (1, 0)): (1+2j), ((3, 1), (1, 0)): -1.7}\n"
     ]
    }
   ],
   "source": [
    "op = of.FermionOperator(\"4^ 3^ 9 1\", 1 + 2j) + of.FermionOperator(\"3^ 1\", -1.7)\n",
    "\n",
    "print(op.terms)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "hRrwfjR55sHZ"
   },
   "source": [
    "Just print the operator for a nice readable representation:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {
    "id": "VYnPilSU5sHa"
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "-1.7 [3^ 1] +\n",
      "(1+2j) [4^ 3^ 9 1]\n"
     ]
    }
   ],
   "source": [
    "print(op)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "vvZxYedI5sHw"
   },
   "source": [
    "### `openfermion.QubitOperator`\n",
    "\n",
    "Same as `FermionOperator`, but the possible actions are 'X', 'Y', and 'Z' instead of 1 and 0."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {
    "id": "79UFeqFz5sHw"
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "1.0 [X1 Y2 Z3] +\n",
      "3.0 [X3 Z4]\n"
     ]
    }
   ],
   "source": [
    "op = of.QubitOperator(((1, \"X\"), (2, \"Y\"), (3, \"Z\")))\n",
    "op += of.QubitOperator(\"X3 Z4\", 3.0)\n",
    "\n",
    "print(op)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "v_PQSbeB5sH1"
   },
   "source": [
    "`FermionOperator` and `QubitOperator` actually inherit from the same parent class: `openfermion.SymbolicOperator`."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "AE28NBCu5sH5"
   },
   "source": [
    "## The Jordan-Wigner and Bravyi-Kitaev transforms\n",
    "\n",
    "A fermionic transform maps `FermionOperator`s to `QubitOperator`s in a way that preserves the canonical anticommutation relations. The most basic transforms are the Jordan-Wigner transform (JWT) and Bravyi-Kitaev transform (BKT). Note that the BKT requires the total number of qubits to be predetermined. Whenever a fermionic transform is being applied implicitly, it is the JWT."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {
    "id": "Cum2qpwA5sH6"
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "(0.25+0j) [X2 Z3 Z4 Z5 Z6 Z7 Z8 Z9 Z10 Z11 Z12 Z13 Z14 X15] +\n",
      "0.25j [X2 Z3 Z4 Z5 Z6 Z7 Z8 Z9 Z10 Z11 Z12 Z13 Z14 Y15] +\n",
      "-0.25j [Y2 Z3 Z4 Z5 Z6 Z7 Z8 Z9 Z10 Z11 Z12 Z13 Z14 X15] +\n",
      "(0.25+0j) [Y2 Z3 Z4 Z5 Z6 Z7 Z8 Z9 Z10 Z11 Z12 Z13 Z14 Y15]\n",
      "\n",
      "(-0.25+0j) [Z1 X2 X3 X7 Z15] +\n",
      "-0.25j [Z1 X2 X3 Y7 Z11 Z13 Z14] +\n",
      "0.25j [Z1 Y2 X3 X7 Z15] +\n",
      "(-0.25+0j) [Z1 Y2 X3 Y7 Z11 Z13 Z14]\n"
     ]
    }
   ],
   "source": [
    "op = of.FermionOperator(\"2^ 15\")\n",
    "\n",
    "print(of.jordan_wigner(op))\n",
    "print()\n",
    "print(of.bravyi_kitaev(op, n_qubits=16))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "9T6yt_Nu5sH_"
   },
   "source": [
    "### Exercise\n",
    "\n",
    "Below are some examples of how `FermionOperator`s are mapped to `QubitOperator`s by the Jordan-Wigner transform (the notation 'h.c.' stands for 'hermitian conjugate'):\n",
    "$$\n",
    "\\begin{align*}\n",
    "    a_p^\\dagger &\\mapsto \\frac12 (X_p - i Y_p) Z_0 \\cdots Z_{p-1}\\\\\n",
    "    a_p^\\dagger a_p &\\mapsto \\frac12 (I - Z_p)\\\\\n",
    "    (\\beta a_p^\\dagger a_q + \\text{h.c.}) &\\mapsto \\frac12 [\\text{Re}(\\beta) (X_p ZZ \\cdots ZZ X_q + Y_p ZZ \\cdots ZZ Y_q) + \\text{Im}(\\beta) (Y_p ZZ \\cdots ZZ X_q - X_p ZZ \\cdots ZZ Y_q)]\n",
    "\\end{align*}\n",
    "$$\n",
    "Verify these mappings for $p=2$ and $q=7$. The `openfermion.hermitian_conjugated` function may be useful here."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {
    "id": "o1bOGrkvUHVq"
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "0.5 [Z0 Z1 X2] +\n",
      "0.5j [Z0 Z1 Y2]\n",
      "\n",
      "(0.5+0j) [] +\n",
      "(-0.5+0j) [Z2]\n",
      "\n",
      "(0.5+0j) [X2 Z3 Z4 Z5 Z6 X7] +\n",
      "(-1+0j) [X2 Z3 Z4 Z5 Z6 Y7] +\n",
      "(1+0j) [Y2 Z3 Z4 Z5 Z6 X7] +\n",
      "(0.5+0j) [Y2 Z3 Z4 Z5 Z6 Y7]\n"
     ]
    }
   ],
   "source": [
    "a2 = of.FermionOperator(\"2\")\n",
    "print(of.jordan_wigner(a2))\n",
    "print()\n",
    "\n",
    "a2dag = of.FermionOperator(\"2^\")\n",
    "print(of.jordan_wigner(a2dag * a2))\n",
    "print()\n",
    "\n",
    "a7 = of.FermionOperator(\"7\")\n",
    "a7dag = of.FermionOperator(\"7^\")\n",
    "print(of.jordan_wigner((1 + 2j) * (a2dag * a7) + (1 - 2j) * (a7dag * a2)))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "gSwBGl9UUy1k"
   },
   "source": [
    "### Solution"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {
    "id": "xwDvR6Ol5sIA"
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "0.5 [Z0 Z1 X2] +\n",
      "-0.5j [Z0 Z1 Y2]\n",
      "\n",
      "(0.5+0j) [] +\n",
      "(-0.5+0j) [Z2]\n",
      "\n",
      "(1+0j) [X2 Z3 Z4 Z5 Z6 X7] +\n",
      "(-1.5+0j) [X2 Z3 Z4 Z5 Z6 Y7] +\n",
      "(1.5+0j) [Y2 Z3 Z4 Z5 Z6 X7] +\n",
      "(1+0j) [Y2 Z3 Z4 Z5 Z6 Y7]\n"
     ]
    }
   ],
   "source": [
    "a2 = of.FermionOperator(\"2\")\n",
    "a2dag = of.FermionOperator(\"2^\")\n",
    "a7 = of.FermionOperator(\"7\")\n",
    "a7dag = of.FermionOperator(\"7^\")\n",
    "\n",
    "print(of.jordan_wigner(a2dag))\n",
    "print()\n",
    "print(of.jordan_wigner(a2dag * a2))\n",
    "print()\n",
    "\n",
    "op = (2 + 3j) * a2dag * a7\n",
    "op += of.hermitian_conjugated(op)\n",
    "print(of.jordan_wigner(op))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "j2BmxWOu5sIC"
   },
   "source": [
    "### Exercise\n",
    "\n",
    "Use the `+` and `*` operators to verify that after applying the JWT to ladder operators, the resulting `QubitOperator`s satisfy\n",
    "$$\n",
    "\\begin{align}\n",
    "    a_2 a_7 + a_7 a_2 &= 0 \\\\\n",
    "    a_2 a_7^\\dagger + a_7^\\dagger a_2 &= 0\\\\\n",
    "    a_2 a_2^\\dagger + a_2^\\dagger a_2 &= 1\n",
    "\\end{align}\n",
    "$$"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "VsJlMb_GVU1Y"
   },
   "source": [
    "### Solution"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {
    "id": "yzwsrS1O5sID"
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "0\n",
      "0\n",
      "(1+0j) []\n"
     ]
    }
   ],
   "source": [
    "a2_jw = of.jordan_wigner(a2)\n",
    "a2dag_jw = of.jordan_wigner(a2dag)\n",
    "a7_jw = of.jordan_wigner(a7)\n",
    "a7dag_jw = of.jordan_wigner(a7dag)\n",
    "\n",
    "print(a2_jw * a7_jw + a7_jw * a2_jw)\n",
    "print(a2_jw * a7dag_jw + a7dag_jw * a2_jw)\n",
    "print(a2_jw * a2dag_jw + a2dag_jw * a2_jw)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "p1fQ3-DK5sIS"
   },
   "source": [
    "## Array data structures\n",
    "\n",
    "- When `FermionOperator`s have specialized structure we can store coefficients in numpy arrays, enabling fast numerical manipulation.\n",
    "- Array data structures can always be converted to `FermionOperator` using `openfermion.get_fermion_operator`.\n",
    "\n",
    "### InteractionOperator\n",
    "\n",
    "- Stores the one- and two-body tensors $T_{pq}$ and $V_{pqrs}$ of the molecular Hamiltonian\n",
    "\n",
    "$$\n",
    "\\sum_{pq} T_{pq} a_p^\\dagger a_q + \\sum_{pqrs} V_{pqrs} a_p^\\dagger a_q^\\dagger a_r a_s\n",
    "$$\n",
    "\n",
    "- Default data structure for molecular Hamiltonians\n",
    "- Convert from `FermionOperator` using `openfermion.get_interaction_operator`\n",
    "\n",
    "### DiagonalCoulombHamiltonian\n",
    "\n",
    "- Stores the one- and two-body coefficient matrices $T_{pq}$ and $V_{pq}$ of a Hamiltonian with a diagonal Coulomb term:\n",
    "\n",
    "$$\n",
    "\\sum_{pq} T_{pq} a_p^\\dagger a_q + \\sum_{pq} V_{pq} a_p^\\dagger a_p a_q^\\dagger a_q\n",
    "$$\n",
    "\n",
    "- Leads to especially efficient algorithms for quantum simulation\n",
    "- Convert from `FermionOperator` using `openfermion.get_diagonal_coulomb_hamiltonian`\n",
    "\n",
    "### QuadraticHamiltonian\n",
    "\n",
    "- Stores the Hermitian matrix $M_{pq}$ and antisymmetric matrix $\\Delta_{pq}$ describing a general quadratic Hamiltonian\n",
    "\n",
    "$$\n",
    "\\sum_{p, q} M_{pq} a^\\dagger_p a_q + \\frac12 \\sum_{p, q} (\\Delta_{pq} a^\\dagger_p a^\\dagger_q + \\text{h.c.})\n",
    "$$\n",
    "\n",
    "- Routines included for efficient diagonalization (can handle thousands of fermionic modes)\n",
    "- Convert from `FermionOperator` using `openfermion.get_quadratic_hamiltonian`"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "fN6Bq0gbdK5G"
   },
   "source": [
    "## Generating the Hamiltonian for a molecule"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "l_UXxxqw5sIW"
   },
   "source": [
    "The cell below demonstrates using one of our electronic structure package plugins, OpenFermion-PySCF, to generate a molecular Hamiltonian for a hydrogen molecule. Note that the Hamiltonian is returned as an `InteractionOperator`. We'll convert it to a `FermionOperator` and print the result."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {
    "id": "r8mmL0aj5sIW"
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "0.66147151365 [] +\n",
      "-1.2178260299951058 [0^ 0] +\n",
      "0.3316650744318082 [0^ 0^ 0 0] +\n",
      "0.09231339177803066 [0^ 0^ 2 2] +\n",
      "0.3316650744318082 [0^ 1^ 1 0] +\n",
      "0.09231339177803066 [0^ 1^ 3 2] +\n",
      "0.09231339177803066 [0^ 2^ 0 2] +\n",
      "0.3267206861819477 [0^ 2^ 2 0] +\n",
      "0.09231339177803066 [0^ 3^ 1 2] +\n",
      "0.3267206861819477 [0^ 3^ 3 0] +\n",
      "0.3316650744318082 [1^ 0^ 0 1] +\n",
      "0.09231339177803066 [1^ 0^ 2 3] +\n",
      "-1.2178260299951058 [1^ 1] +\n",
      "0.3316650744318082 [1^ 1^ 1 1] +\n",
      "0.09231339177803066 [1^ 1^ 3 3] +\n",
      "0.09231339177803066 [1^ 2^ 0 3] +\n",
      "0.3267206861819477 [1^ 2^ 2 1] +\n",
      "0.09231339177803066 [1^ 3^ 1 3] +\n",
      "0.3267206861819477 [1^ 3^ 3 1] +\n",
      "0.32672068618194783 [2^ 0^ 0 2] +\n",
      "0.09231339177803066 [2^ 0^ 2 0] +\n",
      "0.32672068618194783 [2^ 1^ 1 2] +\n",
      "0.09231339177803066 [2^ 1^ 3 0] +\n",
      "-0.5096378744364826 [2^ 2] +\n",
      "0.09231339177803066 [2^ 2^ 0 0] +\n",
      "0.34339576784573445 [2^ 2^ 2 2] +\n",
      "0.09231339177803066 [2^ 3^ 1 0] +\n",
      "0.34339576784573445 [2^ 3^ 3 2] +\n",
      "0.32672068618194783 [3^ 0^ 0 3] +\n",
      "0.09231339177803066 [3^ 0^ 2 1] +\n",
      "0.32672068618194783 [3^ 1^ 1 3] +\n",
      "0.09231339177803066 [3^ 1^ 3 1] +\n",
      "0.09231339177803066 [3^ 2^ 0 1] +\n",
      "0.34339576784573445 [3^ 2^ 2 3] +\n",
      "-0.5096378744364826 [3^ 3] +\n",
      "0.09231339177803066 [3^ 3^ 1 1] +\n",
      "0.34339576784573445 [3^ 3^ 3 3]\n"
     ]
    }
   ],
   "source": [
    "# Set molecule parameters\n",
    "geometry = [(\"H\", (0.0, 0.0, 0.0)), (\"H\", (0.0, 0.0, 0.8))]\n",
    "basis = \"sto-3g\"\n",
    "multiplicity = 1\n",
    "charge = 0\n",
    "\n",
    "# Perform electronic structure calculations and\n",
    "# obtain Hamiltonian as an InteractionOperator\n",
    "hamiltonian = ofpyscf.generate_molecular_hamiltonian(\n",
    "    geometry, basis, multiplicity, charge\n",
    ")\n",
    "\n",
    "# Convert to a FermionOperator\n",
    "hamiltonian_ferm_op = of.get_fermion_operator(hamiltonian)\n",
    "\n",
    "print(hamiltonian_ferm_op)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "jWxU4bG1oYfZ"
   },
   "source": [
    "Let's calculate the ground energy (lowest eigenvalue) of the Hamiltonian. First, we'll map the `FermionOperator` to a `QubitOperator` using the JWT. Then, we'll convert the `QubitOperator` to a SciPy sparse matrix and get its lowest eigenvalue."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {
    "id": "rIEH_5eLaxvG"
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Ground_energy: -1.134147666677095\n",
      "JWT transformed Hamiltonian:\n",
      "(-0.16733398905695201+0j) [] +\n",
      "(-0.04615669588901533+0j) [X0 X1 Y2 Y3] +\n",
      "(0.04615669588901533+0j) [X0 Y1 Y2 X3] +\n",
      "(0.04615669588901533+0j) [Y0 X1 X2 Y3] +\n",
      "(-0.04615669588901533+0j) [Y0 Y1 X2 X3] +\n",
      "(0.16251648748871642+0j) [Z0] +\n",
      "(0.1658325372159041+0j) [Z0 Z1] +\n",
      "(0.11720364720195856+0j) [Z0 Z2] +\n",
      "(0.1633603430909739+0j) [Z0 Z3] +\n",
      "(0.16251648748871636+0j) [Z1] +\n",
      "(0.1633603430909739+0j) [Z1 Z2] +\n",
      "(0.11720364720195856+0j) [Z1 Z3] +\n",
      "(-0.1974429369975584+0j) [Z2] +\n",
      "(0.17169788392286722+0j) [Z2 Z3] +\n",
      "(-0.19744293699755838+0j) [Z3]\n"
     ]
    }
   ],
   "source": [
    "# Map to QubitOperator using the JWT\n",
    "hamiltonian_jw = of.jordan_wigner(hamiltonian_ferm_op)\n",
    "\n",
    "# Convert to Scipy sparse matrix\n",
    "hamiltonian_jw_sparse = of.get_sparse_operator(hamiltonian_jw)\n",
    "\n",
    "# Compute ground energy\n",
    "eigs, _ = linalg.eigsh(hamiltonian_jw_sparse, k=1, which=\"SA\")\n",
    "ground_energy = eigs[0]\n",
    "\n",
    "print(\"Ground_energy: {}\".format(ground_energy))\n",
    "print(\"JWT transformed Hamiltonian:\")\n",
    "print(hamiltonian_jw)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "gjUBgFx-axmm"
   },
   "source": [
    "### Exercise\n",
    "Compute the ground energy of the same Hamiltonian, but via the Bravyi-Kitaev transform. Verify that you get the same value."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {
    "id": "ID2vls21XKj-"
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Ground_energy: -1.1341476666770918\n",
      "BK transformed Hamiltonian:\n",
      "(-0.16733398905695201+0j) [] +\n",
      "(0.04615669588901533+0j) [X0 Z1 X2] +\n",
      "(0.04615669588901533+0j) [X0 Z1 X2 Z3] +\n",
      "(0.04615669588901533+0j) [Y0 Z1 Y2] +\n",
      "(0.04615669588901533+0j) [Y0 Z1 Y2 Z3] +\n",
      "(0.16251648748871642+0j) [Z0] +\n",
      "(0.16251648748871636+0j) [Z0 Z1] +\n",
      "(0.1633603430909739+0j) [Z0 Z1 Z2] +\n",
      "(0.1633603430909739+0j) [Z0 Z1 Z2 Z3] +\n",
      "(0.11720364720195856+0j) [Z0 Z2] +\n",
      "(0.11720364720195856+0j) [Z0 Z2 Z3] +\n",
      "(0.1658325372159041+0j) [Z1] +\n",
      "(-0.19744293699755838+0j) [Z1 Z2 Z3] +\n",
      "(0.17169788392286722+0j) [Z1 Z3] +\n",
      "(-0.1974429369975584+0j) [Z2]\n"
     ]
    }
   ],
   "source": [
    "# Map to QubitOperator using the JWT\n",
    "hamiltonian_bk = of.bravyi_kitaev(hamiltonian_ferm_op)\n",
    "\n",
    "# Convert to Scipy sparse matrix\n",
    "hamiltonian_bk_sparse = of.get_sparse_operator(hamiltonian_bk)\n",
    "\n",
    "# Compute ground energy\n",
    "eigs, _ = linalg.eigsh(hamiltonian_bk_sparse, k=1, which=\"SA\")\n",
    "ground_energy = eigs[0]\n",
    "\n",
    "print(\"Ground_energy: {}\".format(ground_energy))\n",
    "print(\"BK transformed Hamiltonian:\")\n",
    "print(hamiltonian_bk)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "dEqS3XV0eXx1"
   },
   "source": [
    "### Solution"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "metadata": {
    "id": "9Ss_OhXo5sIP"
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Ground_energy: -1.134147666677097\n",
      "BKT transformed Hamiltonian:\n",
      "(-0.16733398905695201+0j) [] +\n",
      "(0.04615669588901533+0j) [X0 Z1 X2] +\n",
      "(0.04615669588901533+0j) [X0 Z1 X2 Z3] +\n",
      "(0.04615669588901533+0j) [Y0 Z1 Y2] +\n",
      "(0.04615669588901533+0j) [Y0 Z1 Y2 Z3] +\n",
      "(0.16251648748871642+0j) [Z0] +\n",
      "(0.16251648748871636+0j) [Z0 Z1] +\n",
      "(0.1633603430909739+0j) [Z0 Z1 Z2] +\n",
      "(0.1633603430909739+0j) [Z0 Z1 Z2 Z3] +\n",
      "(0.11720364720195856+0j) [Z0 Z2] +\n",
      "(0.11720364720195856+0j) [Z0 Z2 Z3] +\n",
      "(0.1658325372159041+0j) [Z1] +\n",
      "(-0.19744293699755838+0j) [Z1 Z2 Z3] +\n",
      "(0.17169788392286722+0j) [Z1 Z3] +\n",
      "(-0.1974429369975584+0j) [Z2]\n"
     ]
    }
   ],
   "source": [
    "# Map to QubitOperator using the BKT\n",
    "hamiltonian_bk = of.bravyi_kitaev(hamiltonian_ferm_op)\n",
    "\n",
    "# Convert to Scipy sparse matrix\n",
    "hamiltonian_bk_sparse = of.get_sparse_operator(hamiltonian_bk)\n",
    "\n",
    "# Compute ground state energy\n",
    "eigs, _ = linalg.eigsh(hamiltonian_bk_sparse, k=1, which=\"SA\")\n",
    "ground_energy = eigs[0]\n",
    "\n",
    "print(\"Ground_energy: {}\".format(ground_energy))\n",
    "print(\"BKT transformed Hamiltonian:\")\n",
    "print(hamiltonian_bk)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "H0DLpARr5sIb"
   },
   "source": [
    "### Exercise\n",
    "\n",
    "- The BCS mean-field d-wave model of superconductivity has the Hamiltonian\n",
    "\n",
    "$$\n",
    "H = - t \\sum_{\\langle i,j \\rangle} \\sum_\\sigma (a^\\dagger_{i, \\sigma} a_{j, \\sigma} + a^\\dagger_{j, \\sigma} a_{i, \\sigma}) - \\sum_{\\langle i,j \\rangle} \\Delta_{ij} (a^\\dagger_{i, \\uparrow} a^\\dagger_{j, \\downarrow} - a^\\dagger_{i, \\downarrow} a^\\dagger_{j, \\uparrow} + a_{j, \\downarrow} a_{i, \\uparrow} - a_{j, \\uparrow} a_{i, \\downarrow})\n",
    "$$\n",
    "\n",
    "Use the `mean_field_dwave` function to generate an instance of this model with dimensions 10x10.\n",
    " - Convert the Hamiltonian to a `QubitOperator` with the JWT. What is the length of the longest Pauli string that appears?\n",
    " - Convert the Hamiltonian to a `QubitOperator` with the BKT. What is the length of the longest Pauli string that appears?\n",
    " - Convert the Hamiltonian to a `QuadraticHamiltonian`. Get its ground energy using the `ground_energy` method of `QuadraticHamiltonian`. What would happen if you tried to compute the ground energy by converting to a sparse matrix?"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "Zrnv4DLRuFJM"
   },
   "source": [
    "## Hamiltonian simulation with Trotter formulas\n",
    "\n",
    "- Goal: apply $\\exp(-i H t)$ where $H = \\sum_j H_j$\n",
    "- Use an approximation such as $\\exp(-i H t) \\approx (\\prod_{j=1} \\exp(-i H_j t/r))^r$\n",
    "- Exposed via the `openfermion.simulate_trotter` function\n",
    "- Currently implemented algorithms are from [arXiv:1706.00023](https://arxiv.org/pdf/1706.00023.pdf), [arXiv:1711.04789](https://arxiv.org/pdf/1711.04789.pdf), and [arXiv:1808.02625](https://arxiv.org/pdf/1808.02625.pdf), and are based on the JWT\n",
    "- Currently supported Hamiltonian types: `DiagonalCoulombHamiltonian` and `InteractionOperator`\n",
    "\n",
    "As a demonstration, we'll simulate time evolution under the hydrogen molecule Hamiltonian we generated earlier.\n",
    "\n",
    "First, let's create a random initial state and apply the exact time evolution by matrix exponentiation:\n",
    "\n",
    "$$\n",
    "\\lvert \\psi \\rangle \\mapsto \\exp(-i H t) \\lvert \\psi \\rangle\n",
    "$$"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "metadata": {
    "id": "_e5mbQI61fdT"
   },
   "outputs": [],
   "source": [
    "# Create a random initial state\n",
    "n_qubits = of.count_qubits(hamiltonian)\n",
    "initial_state = of.haar_random_vector(2**n_qubits, seed=7)\n",
    "\n",
    "# Set evolution time\n",
    "time = 1.0\n",
    "\n",
    "# Apply exp(-i H t) to the state\n",
    "exact_state = linalg.expm_multiply(-1j * hamiltonian_jw_sparse * time, initial_state)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "_OZPjkN513zJ"
   },
   "source": [
    "Now, let's create a circuit to perform the evolution and compare the fidelity of the resulting state with the one from exact evolution. The fidelity can be increased by increasing the number of Trotter steps. Note that the Hamiltonian input to `openfermion.simulate_trotter` should be an `InteractionOperator`, not a `FermionOperator`."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "metadata": {
    "id": "1DXSZ54u12Tt"
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "0.9999820449924582\n"
     ]
    }
   ],
   "source": [
    "# Initialize qubits\n",
    "qubits = cirq.LineQubit.range(n_qubits)\n",
    "\n",
    "# Create circuit\n",
    "circuit = cirq.Circuit(\n",
    "    of.simulate_trotter(\n",
    "        qubits, hamiltonian, time, n_steps=10, order=0, algorithm=of.LOW_RANK\n",
    "    )\n",
    ")\n",
    "\n",
    "# Apply the circuit to the initial state\n",
    "result = circuit.final_state_vector(initial_state)\n",
    "\n",
    "# Compute the fidelity with the final state from exact evolution\n",
    "fidelity = abs(np.dot(exact_state, result.conj())) ** 2\n",
    "\n",
    "print(fidelity)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "metadata": {
    "id": "tG4PCh4faFTL"
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "0             1                  2                3\n",
      "│             │                  │                │\n",
      "Rz(0)         Rz(0)              Rz(0)            Rz(0)\n",
      "│             │                  │                │\n",
      "Rz(0.052π)    Rz(0.052π)         Rz(0.03π)        Rz(0.03π)\n",
      "│             │                  │                │\n",
      "Rz(0)         Rz(0)              Rz(0)            Rz(0)\n",
      "│             │                  │                │\n",
      "│             PhISwap(0.25)──────PhISwap(0.25)^-1 │\n",
      "│             │                  │                │\n",
      "PhISwap(0.25)─PhISwap(0.25)^-1   Z^0              │\n",
      "│             │                  │                │\n",
      "│             Z^0                PhISwap(0.25)────PhISwap(0.25)^-1\n",
      "│             │                  │                │\n",
      "│             PhISwap(0.25)──────PhISwap(0.25)^-1 Z^0\n",
      "│             │                  │                │\n",
      "@─────────────@^-0.022           Z^0              │\n",
      "│             │                  │                │\n",
      "×─────────────×                  @────────────────@^-0.021\n",
      "│             │                  │                │\n",
      "│             │                  ×────────────────×\n",
      "│             │                  │                │\n",
      "│             @──────────────────@^-0.021         │\n",
      "│             │                  │                │\n",
      "│             ×──────────────────×                │\n",
      "│             │                  │                │\n",
      "@─────────────@^-0.021           @────────────────@^-0.021\n",
      "│             │                  │                │\n",
      "×─────────────×                  ×────────────────×\n",
      "│             │                  │                │\n",
      "Rz(-0.01π)    @──────────────────@^-0.021         Rz(-0.011π)\n",
      "│             │                  │                │\n",
      "Rz(π)         ×──────────────────×                Rz(π)\n",
      "│             │                  │                │\n",
      "│             Rz(-0.01π)         Rz(-0.011π)      │\n",
      "│             │                  │                │\n",
      "│             Rz(0)              Rz(0)            │\n",
      "│             │                  │                │\n",
      "│             PhISwap(0.25)──────PhISwap(0.25)^-1 │\n",
      "│             │                  │                │\n",
      "│             Z^0                PhISwap(0.25)────PhISwap(0.25)^0.5\n",
      "│             │                  │                │\n",
      "PhISwap(0.25)─PhISwap(0.25)^-0.5 Z^0              │\n",
      "│             │                  │                │\n",
      "Z^0           PhISwap(0.25)──────PhISwap(0.25)^-1 │\n",
      "│             │                  │                │\n",
      "│             Z^0                @────────────────@^-0.006\n",
      "│             │                  │                │\n",
      "@─────────────@^-0.006           ×────────────────×\n",
      "│             │                  │                │\n",
      "×─────────────×                  │                │\n",
      "│             │                  │                │\n",
      "│             @──────────────────@^0.006          │\n",
      "│             │                  │                │\n",
      "│             ×──────────────────×                │\n",
      "│             │                  │                │\n",
      "@─────────────@^0.006            @────────────────@^0.006\n",
      "│             │                  │                │\n",
      "×─────────────×                  ×────────────────×\n",
      "│             │                  │                │\n",
      "Rz(-0.003π)   @──────────────────@^0.006          Rz(-0.003π)\n",
      "│             │                  │                │\n",
      "Rz(π)         ×──────────────────×                Rz(0)\n",
      "│             │                  │                │\n",
      "│             Rz(-0.003π)        Rz(-0.003π)      │\n",
      "│             │                  │                │\n",
      "│             Rz(0)              Rz(π)            │\n",
      "│             │                  │                │\n",
      "│             PhISwap(0.25)──────PhISwap(0.25)^-1 │\n",
      "│             │                  │                │\n",
      "PhISwap(0.25)─PhISwap(0.25)^-0.5 Z^0              │\n",
      "│             │                  │                │\n",
      "│             Z^0                PhISwap(0.25)────PhISwap(0.25)^0.5\n",
      "│             │                  │                │\n",
      "│             PhISwap(0.25)──────PhISwap(0.25)^-1 Z^0\n",
      "│             │                  │                │\n",
      "@─────────────@^0                Z^0              │\n",
      "│             │                  │                │\n",
      "×─────────────×                  @────────────────@^0\n",
      "│             │                  │                │\n",
      "│             │                  ×────────────────×\n",
      "│             │                  │                │\n",
      "│             @──────────────────@^0              │\n",
      "│             │                  │                │\n",
      "│             ×──────────────────×                │\n",
      "│             │                  │                │\n",
      "@─────────────@^0                @────────────────@^0\n",
      "│             │                  │                │\n",
      "×─────────────×                  ×────────────────×\n",
      "│             │                  │                │\n",
      "Rz(0)         @──────────────────@^0              Rz(0)\n",
      "│             │                  │                │\n",
      "Rz(0)         ×──────────────────×                Rz(0)\n",
      "│             │                  │                │\n",
      "Rz(0)         Rz(0)              Rz(0)            Rz(0)\n",
      "│             │                  │                │\n",
      "Rz(0.03π)     Rz(0)              Rz(0)            Rz(0.052π)\n",
      "│             │                  │                │\n",
      "Rz(0)         Rz(0)              Rz(0)            Rz(0)\n",
      "│             │                  │                │\n",
      "│             Rz(0.03π)          Rz(0.052π)       │\n",
      "│             │                  │                │\n",
      "│             Rz(0)              Rz(0)            │\n",
      "│             │                  │                │\n",
      "│             PhISwap(0.25)──────PhISwap(0.25)^-1 │\n",
      "│             │                  │                │\n",
      "│             Z^0                PhISwap(0.25)────PhISwap(0.25)^-1\n",
      "│             │                  │                │\n",
      "PhISwap(0.25)─PhISwap(0.25)^-1   Z^0              │\n",
      "│             │                  │                │\n",
      "Z^0           PhISwap(0.25)──────PhISwap(0.25)^-1 │\n",
      "│             │                  │                │\n",
      "│             Z^0                @────────────────@^-0.022\n",
      "│             │                  │                │\n",
      "@─────────────@^-0.021           ×────────────────×\n",
      "│             │                  │                │\n",
      "×─────────────×                  │                │\n",
      "│             │                  │                │\n",
      "│             @──────────────────@^-0.021         │\n",
      "│             │                  │                │\n",
      "│             ×──────────────────×                │\n",
      "│             │                  │                │\n",
      "@─────────────@^-0.021           @────────────────@^-0.021\n",
      "│             │                  │                │\n",
      "×─────────────×                  ×────────────────×\n",
      "│             │                  │                │\n",
      "Rz(-0.011π)   @──────────────────@^-0.021         Rz(-0.01π)\n",
      "│             │                  │                │\n",
      "Rz(π)         ×──────────────────×                Rz(π)\n",
      "│             │                  │                │\n",
      "│             Rz(-0.011π)        Rz(-0.01π)       │\n",
      "│             │                  │                │\n",
      "│             Rz(0)              Rz(0)            │\n",
      "│             │                  │                │\n",
      "│             PhISwap(0.25)──────PhISwap(0.25)^-1 │\n",
      "│             │                  │                │\n",
      "PhISwap(0.25)─PhISwap(0.25)^0.5  Z^0              │\n",
      "│             │                  │                │\n",
      "│             Z^0                PhISwap(0.25)────PhISwap(0.25)^-0.5\n",
      "│             │                  │                │\n",
      "│             PhISwap(0.25)──────PhISwap(0.25)^-1 Z^0\n",
      "│             │                  │                │\n",
      "@─────────────@^-0.006           Z^0              │\n",
      "│             │                  │                │\n",
      "×─────────────×                  @────────────────@^-0.006\n",
      "│             │                  │                │\n",
      "│             │                  ×────────────────×\n",
      "│             │                  │                │\n",
      "│             @──────────────────@^0.006          │\n",
      "│             │                  │                │\n",
      "│             ×──────────────────×                │\n",
      "│             │                  │                │\n",
      "@─────────────@^0.006            @────────────────@^0.006\n",
      "│             │                  │                │\n",
      "×─────────────×                  ×────────────────×\n",
      "│             │                  │                │\n",
      "Rz(-0.003π)   @──────────────────@^0.006          Rz(-0.003π)\n",
      "│             │                  │                │\n",
      "Rz(0)         ×──────────────────×                Rz(π)\n",
      "│             │                  │                │\n",
      "│             Rz(-0.003π)        Rz(-0.003π)      │\n",
      "│             │                  │                │\n",
      "│             Rz(π)              Rz(0)            │\n",
      "│             │                  │                │\n",
      "│             PhISwap(0.25)──────PhISwap(0.25)^-1 │\n",
      "│             │                  │                │\n",
      "│             Z^0                PhISwap(0.25)────PhISwap(0.25)^-0.5\n",
      "│             │                  │                │\n",
      "PhISwap(0.25)─PhISwap(0.25)^0.5  Z^0              │\n",
      "│             │                  │                │\n",
      "Z^0           PhISwap(0.25)──────PhISwap(0.25)^-1 │\n",
      "│             │                  │                │\n",
      "│             Z^0                @────────────────@^0\n",
      "│             │                  │                │\n",
      "@─────────────@^0                ×────────────────×\n",
      "│             │                  │                │\n",
      "×─────────────×                  │                │\n",
      "│             │                  │                │\n",
      "│             @──────────────────@^0              │\n",
      "│             │                  │                │\n",
      "│             ×──────────────────×                │\n",
      "│             │                  │                │\n",
      "@─────────────@^0                @────────────────@^0\n",
      "│             │                  │                │\n",
      "×─────────────×                  ×────────────────×\n",
      "│             │                  │                │\n",
      "Rz(0)         @──────────────────@^0              Rz(0)\n",
      "│             │                  │                │\n",
      "Rz(0)         ×──────────────────×                Rz(0)\n",
      "│             │                  │                │\n",
      "Rz(0)         Rz(0)              Rz(0)            Rz(0)\n",
      "│             │                  │                │\n",
      "Rz(0.052π)    Rz(0)              Rz(0)            Rz(0.03π)\n",
      "│             │                  │                │\n",
      "Rz(0)         Rz(0)              Rz(0)            Rz(0)\n",
      "│             │                  │                │\n",
      "│             Rz(0.052π)         Rz(0.03π)        │\n",
      "│             │                  │                │\n",
      "│             Rz(0)              Rz(0)            │\n",
      "│             │                  │                │\n",
      "│             PhISwap(0.25)──────PhISwap(0.25)^-1 │\n",
      "│             │                  │                │\n",
      "PhISwap(0.25)─PhISwap(0.25)^-1   Z^0              │\n",
      "│             │                  │                │\n",
      "│             Z^0                PhISwap(0.25)────PhISwap(0.25)^-1\n",
      "│             │                  │                │\n",
      "│             PhISwap(0.25)──────PhISwap(0.25)^-1 Z^0\n",
      "│             │                  │                │\n",
      "@─────────────@^-0.022           Z^0              │\n",
      "│             │                  │                │\n",
      "×─────────────×                  @────────────────@^-0.021\n",
      "│             │                  │                │\n",
      "│             │                  ×────────────────×\n",
      "│             │                  │                │\n",
      "│             @──────────────────@^-0.021         │\n",
      "│             │                  │                │\n",
      "│             ×──────────────────×                │\n",
      "│             │                  │                │\n",
      "@─────────────@^-0.021           @────────────────@^-0.021\n",
      "│             │                  │                │\n",
      "×─────────────×                  ×────────────────×\n",
      "│             │                  │                │\n",
      "Rz(-0.01π)    @──────────────────@^-0.021         Rz(-0.011π)\n",
      "│             │                  │                │\n",
      "Rz(π)         ×──────────────────×                Rz(π)\n",
      "│             │                  │                │\n",
      "│             Rz(-0.01π)         Rz(-0.011π)      │\n",
      "│             │                  │                │\n",
      "│             Rz(0)              Rz(0)            │\n",
      "│             │                  │                │\n",
      "│             PhISwap(0.25)──────PhISwap(0.25)^-1 │\n",
      "│             │                  │                │\n",
      "│             Z^0                PhISwap(0.25)────PhISwap(0.25)^0.5\n",
      "│             │                  │                │\n",
      "PhISwap(0.25)─PhISwap(0.25)^-0.5 Z^0              │\n",
      "│             │                  │                │\n",
      "Z^0           PhISwap(0.25)──────PhISwap(0.25)^-1 │\n",
      "│             │                  │                │\n",
      "│             Z^0                @────────────────@^-0.006\n",
      "│             │                  │                │\n",
      "@─────────────@^-0.006           ×────────────────×\n",
      "│             │                  │                │\n",
      "×─────────────×                  │                │\n",
      "│             │                  │                │\n",
      "│             @──────────────────@^0.006          │\n",
      "│             │                  │                │\n",
      "│             ×──────────────────×                │\n",
      "│             │                  │                │\n",
      "@─────────────@^0.006            @────────────────@^0.006\n",
      "│             │                  │                │\n",
      "×─────────────×                  ×────────────────×\n",
      "│             │                  │                │\n",
      "Rz(-0.003π)   @──────────────────@^0.006          Rz(-0.003π)\n",
      "│             │                  │                │\n",
      "Rz(π)         ×──────────────────×                Rz(0)\n",
      "│             │                  │                │\n",
      "│             Rz(-0.003π)        Rz(-0.003π)      │\n",
      "│             │                  │                │\n",
      "│             Rz(0)              Rz(π)            │\n",
      "│             │                  │                │\n",
      "│             PhISwap(0.25)──────PhISwap(0.25)^-1 │\n",
      "│             │                  │                │\n",
      "PhISwap(0.25)─PhISwap(0.25)^-0.5 Z^0              │\n",
      "│             │                  │                │\n",
      "│             Z^0                PhISwap(0.25)────PhISwap(0.25)^0.5\n",
      "│             │                  │                │\n",
      "│             PhISwap(0.25)──────PhISwap(0.25)^-1 Z^0\n",
      "│             │                  │                │\n",
      "@─────────────@^0                Z^0              │\n",
      "│             │                  │                │\n",
      "×─────────────×                  @────────────────@^0\n",
      "│             │                  │                │\n",
      "│             │                  ×────────────────×\n",
      "│             │                  │                │\n",
      "│             @──────────────────@^0              │\n",
      "│             │                  │                │\n",
      "│             ×──────────────────×                │\n",
      "│             │                  │                │\n",
      "@─────────────@^0                @────────────────@^0\n",
      "│             │                  │                │\n",
      "×─────────────×                  ×────────────────×\n",
      "│             │                  │                │\n",
      "Rz(0)         @──────────────────@^0              Rz(0)\n",
      "│             │                  │                │\n",
      "Rz(0)         ×──────────────────×                Rz(0)\n",
      "│             │                  │                │\n",
      "Rz(0)         Rz(0)              Rz(0)            Rz(0)\n",
      "│             │                  │                │\n",
      "Rz(0.03π)     Rz(0)              Rz(0)            Rz(0.052π)\n",
      "│             │                  │                │\n",
      "Rz(0)         Rz(0)              Rz(0)            Rz(0)\n",
      "│             │                  │                │\n",
      "│             Rz(0.03π)          Rz(0.052π)       │\n",
      "│             │                  │                │\n",
      "│             Rz(0)              Rz(0)            │\n",
      "│             │                  │                │\n",
      "│             PhISwap(0.25)──────PhISwap(0.25)^-1 │\n",
      "│             │                  │                │\n",
      "│             Z^0                PhISwap(0.25)────PhISwap(0.25)^-1\n",
      "│             │                  │                │\n",
      "PhISwap(0.25)─PhISwap(0.25)^-1   Z^0              │\n",
      "│             │                  │                │\n",
      "Z^0           PhISwap(0.25)──────PhISwap(0.25)^-1 │\n",
      "│             │                  │                │\n",
      "│             Z^0                @────────────────@^-0.022\n",
      "│             │                  │                │\n",
      "@─────────────@^-0.021           ×────────────────×\n",
      "│             │                  │                │\n",
      "×─────────────×                  │                │\n",
      "│             │                  │                │\n",
      "│             @──────────────────@^-0.021         │\n",
      "│             │                  │                │\n",
      "│             ×──────────────────×                │\n",
      "│             │                  │                │\n",
      "@─────────────@^-0.021           @────────────────@^-0.021\n",
      "│             │                  │                │\n",
      "×─────────────×                  ×────────────────×\n",
      "│             │                  │                │\n",
      "Rz(-0.011π)   @──────────────────@^-0.021         Rz(-0.01π)\n",
      "│             │                  │                │\n",
      "Rz(π)         ×──────────────────×                Rz(π)\n",
      "│             │                  │                │\n",
      "│             Rz(-0.011π)        Rz(-0.01π)       │\n",
      "│             │                  │                │\n",
      "│             Rz(0)              Rz(0)            │\n",
      "│             │                  │                │\n",
      "│             PhISwap(0.25)──────PhISwap(0.25)^-1 │\n",
      "│             │                  │                │\n",
      "PhISwap(0.25)─PhISwap(0.25)^0.5  Z^0              │\n",
      "│             │                  │                │\n",
      "│             Z^0                PhISwap(0.25)────PhISwap(0.25)^-0.5\n",
      "│             │                  │                │\n",
      "│             PhISwap(0.25)──────PhISwap(0.25)^-1 Z^0\n",
      "│             │                  │                │\n",
      "@─────────────@^-0.006           Z^0              │\n",
      "│             │                  │                │\n",
      "×─────────────×                  @────────────────@^-0.006\n",
      "│             │                  │                │\n",
      "│             │                  ×────────────────×\n",
      "│             │                  │                │\n",
      "│             @──────────────────@^0.006          │\n",
      "│             │                  │                │\n",
      "│             ×──────────────────×                │\n",
      "│             │                  │                │\n",
      "@─────────────@^0.006            @────────────────@^0.006\n",
      "│             │                  │                │\n",
      "×─────────────×                  ×────────────────×\n",
      "│             │                  │                │\n",
      "Rz(-0.003π)   @──────────────────@^0.006          Rz(-0.003π)\n",
      "│             │                  │                │\n",
      "Rz(0)         ×──────────────────×                Rz(π)\n",
      "│             │                  │                │\n",
      "│             Rz(-0.003π)        Rz(-0.003π)      │\n",
      "│             │                  │                │\n",
      "│             Rz(π)              Rz(0)            │\n",
      "│             │                  │                │\n",
      "│             PhISwap(0.25)──────PhISwap(0.25)^-1 │\n",
      "│             │                  │                │\n",
      "│             Z^0                PhISwap(0.25)────PhISwap(0.25)^-0.5\n",
      "│             │                  │                │\n",
      "PhISwap(0.25)─PhISwap(0.25)^0.5  Z^0              │\n",
      "│             │                  │                │\n",
      "Z^0           PhISwap(0.25)──────PhISwap(0.25)^-1 │\n",
      "│             │                  │                │\n",
      "│             Z^0                @────────────────@^0\n",
      "│             │                  │                │\n",
      "@─────────────@^0                ×────────────────×\n",
      "│             │                  │                │\n",
      "×─────────────×                  │                │\n",
      "│             │                  │                │\n",
      "│             @──────────────────@^0              │\n",
      "│             │                  │                │\n",
      "│             ×──────────────────×                │\n",
      "│             │                  │                │\n",
      "@─────────────@^0                @────────────────@^0\n",
      "│             │                  │                │\n",
      "×─────────────×                  ×────────────────×\n",
      "│             │                  │                │\n",
      "Rz(0)         @──────────────────@^0              Rz(0)\n",
      "│             │                  │                │\n",
      "Rz(0)         ×──────────────────×                Rz(0)\n",
      "│             │                  │                │\n",
      "Rz(0)         Rz(0)              Rz(0)            Rz(0)\n",
      "│             │                  │                │\n",
      "Rz(0.052π)    Rz(0)              Rz(0)            Rz(0.03π)\n",
      "│             │                  │                │\n",
      "Rz(0)         Rz(0)              Rz(0)            Rz(0)\n",
      "│             │                  │                │\n",
      "│             Rz(0.052π)         Rz(0.03π)        │\n",
      "│             │                  │                │\n",
      "│             Rz(0)              Rz(0)            │\n",
      "│             │                  │                │\n",
      "│             PhISwap(0.25)──────PhISwap(0.25)^-1 │\n",
      "│             │                  │                │\n",
      "PhISwap(0.25)─PhISwap(0.25)^-1   Z^0              │\n",
      "│             │                  │                │\n",
      "│             Z^0                PhISwap(0.25)────PhISwap(0.25)^-1\n",
      "│             │                  │                │\n",
      "│             PhISwap(0.25)──────PhISwap(0.25)^-1 Z^0\n",
      "│             │                  │                │\n",
      "@─────────────@^-0.022           Z^0              │\n",
      "│             │                  │                │\n",
      "×─────────────×                  @────────────────@^-0.021\n",
      "│             │                  │                │\n",
      "│             │                  ×────────────────×\n",
      "│             │                  │                │\n",
      "│             @──────────────────@^-0.021         │\n",
      "│             │                  │                │\n",
      "│             ×──────────────────×                │\n",
      "│             │                  │                │\n",
      "@─────────────@^-0.021           @────────────────@^-0.021\n",
      "│             │                  │                │\n",
      "×─────────────×                  ×────────────────×\n",
      "│             │                  │                │\n",
      "Rz(-0.01π)    @──────────────────@^-0.021         Rz(-0.011π)\n",
      "│             │                  │                │\n",
      "Rz(π)         ×──────────────────×                Rz(π)\n",
      "│             │                  │                │\n",
      "│             Rz(-0.01π)         Rz(-0.011π)      │\n",
      "│             │                  │                │\n",
      "│             Rz(0)              Rz(0)            │\n",
      "│             │                  │                │\n",
      "│             PhISwap(0.25)──────PhISwap(0.25)^-1 │\n",
      "│             │                  │                │\n",
      "│             Z^0                PhISwap(0.25)────PhISwap(0.25)^0.5\n",
      "│             │                  │                │\n",
      "PhISwap(0.25)─PhISwap(0.25)^-0.5 Z^0              │\n",
      "│             │                  │                │\n",
      "Z^0           PhISwap(0.25)──────PhISwap(0.25)^-1 │\n",
      "│             │                  │                │\n",
      "│             Z^0                @────────────────@^-0.006\n",
      "│             │                  │                │\n",
      "@─────────────@^-0.006           ×────────────────×\n",
      "│             │                  │                │\n",
      "×─────────────×                  │                │\n",
      "│             │                  │                │\n",
      "│             @──────────────────@^0.006          │\n",
      "│             │                  │                │\n",
      "│             ×──────────────────×                │\n",
      "│             │                  │                │\n",
      "@─────────────@^0.006            @────────────────@^0.006\n",
      "│             │                  │                │\n",
      "×─────────────×                  ×────────────────×\n",
      "│             │                  │                │\n",
      "Rz(-0.003π)   @──────────────────@^0.006          Rz(-0.003π)\n",
      "│             │                  │                │\n",
      "Rz(π)         ×──────────────────×                Rz(0)\n",
      "│             │                  │                │\n",
      "│             Rz(-0.003π)        Rz(-0.003π)      │\n",
      "│             │                  │                │\n",
      "│             Rz(0)              Rz(π)            │\n",
      "│             │                  │                │\n",
      "│             PhISwap(0.25)──────PhISwap(0.25)^-1 │\n",
      "│             │                  │                │\n",
      "PhISwap(0.25)─PhISwap(0.25)^-0.5 Z^0              │\n",
      "│             │                  │                │\n",
      "│             Z^0                PhISwap(0.25)────PhISwap(0.25)^0.5\n",
      "│             │                  │                │\n",
      "│             PhISwap(0.25)──────PhISwap(0.25)^-1 Z^0\n",
      "│             │                  │                │\n",
      "@─────────────@^0                Z^0              │\n",
      "│             │                  │                │\n",
      "×─────────────×                  @────────────────@^0\n",
      "│             │                  │                │\n",
      "│             │                  ×────────────────×\n",
      "│             │                  │                │\n",
      "│             @──────────────────@^0              │\n",
      "│             │                  │                │\n",
      "│             ×──────────────────×                │\n",
      "│             │                  │                │\n",
      "@─────────────@^0                @────────────────@^0\n",
      "│             │                  │                │\n",
      "×─────────────×                  ×────────────────×\n",
      "│             │                  │                │\n",
      "Rz(0)         @──────────────────@^0              Rz(0)\n",
      "│             │                  │                │\n",
      "Rz(0)         ×──────────────────×                Rz(0)\n",
      "│             │                  │                │\n",
      "Rz(0)         Rz(0)              Rz(0)            Rz(0)\n",
      "│             │                  │                │\n",
      "Rz(0.03π)     Rz(0)              Rz(0)            Rz(0.052π)\n",
      "│             │                  │                │\n",
      "Rz(0)         Rz(0)              Rz(0)            Rz(0)\n",
      "│             │                  │                │\n",
      "│             Rz(0.03π)          Rz(0.052π)       │\n",
      "│             │                  │                │\n",
      "│             Rz(0)              Rz(0)            │\n",
      "│             │                  │                │\n",
      "│             PhISwap(0.25)──────PhISwap(0.25)^-1 │\n",
      "│             │                  │                │\n",
      "│             Z^0                PhISwap(0.25)────PhISwap(0.25)^-1\n",
      "│             │                  │                │\n",
      "PhISwap(0.25)─PhISwap(0.25)^-1   Z^0              │\n",
      "│             │                  │                │\n",
      "Z^0           PhISwap(0.25)──────PhISwap(0.25)^-1 │\n",
      "│             │                  │                │\n",
      "│             Z^0                @────────────────@^-0.022\n",
      "│             │                  │                │\n",
      "@─────────────@^-0.021           ×────────────────×\n",
      "│             │                  │                │\n",
      "×─────────────×                  │                │\n",
      "│             │                  │                │\n",
      "│             @──────────────────@^-0.021         │\n",
      "│             │                  │                │\n",
      "│             ×──────────────────×                │\n",
      "│             │                  │                │\n",
      "@─────────────@^-0.021           @────────────────@^-0.021\n",
      "│             │                  │                │\n",
      "×─────────────×                  ×────────────────×\n",
      "│             │                  │                │\n",
      "Rz(-0.011π)   @──────────────────@^-0.021         Rz(-0.01π)\n",
      "│             │                  │                │\n",
      "Rz(π)         ×──────────────────×                Rz(π)\n",
      "│             │                  │                │\n",
      "│             Rz(-0.011π)        Rz(-0.01π)       │\n",
      "│             │                  │                │\n",
      "│             Rz(0)              Rz(0)            │\n",
      "│             │                  │                │\n",
      "│             PhISwap(0.25)──────PhISwap(0.25)^-1 │\n",
      "│             │                  │                │\n",
      "PhISwap(0.25)─PhISwap(0.25)^0.5  Z^0              │\n",
      "│             │                  │                │\n",
      "│             Z^0                PhISwap(0.25)────PhISwap(0.25)^-0.5\n",
      "│             │                  │                │\n",
      "│             PhISwap(0.25)──────PhISwap(0.25)^-1 Z^0\n",
      "│             │                  │                │\n",
      "@─────────────@^-0.006           Z^0              │\n",
      "│             │                  │                │\n",
      "×─────────────×                  @────────────────@^-0.006\n",
      "│             │                  │                │\n",
      "│             │                  ×────────────────×\n",
      "│             │                  │                │\n",
      "│             @──────────────────@^0.006          │\n",
      "│             │                  │                │\n",
      "│             ×──────────────────×                │\n",
      "│             │                  │                │\n",
      "@─────────────@^0.006            @────────────────@^0.006\n",
      "│             │                  │                │\n",
      "×─────────────×                  ×────────────────×\n",
      "│             │                  │                │\n",
      "Rz(-0.003π)   @──────────────────@^0.006          Rz(-0.003π)\n",
      "│             │                  │                │\n",
      "Rz(0)         ×──────────────────×                Rz(π)\n",
      "│             │                  │                │\n",
      "│             Rz(-0.003π)        Rz(-0.003π)      │\n",
      "│             │                  │                │\n",
      "│             Rz(π)              Rz(0)            │\n",
      "│             │                  │                │\n",
      "│             PhISwap(0.25)──────PhISwap(0.25)^-1 │\n",
      "│             │                  │                │\n",
      "│             Z^0                PhISwap(0.25)────PhISwap(0.25)^-0.5\n",
      "│             │                  │                │\n",
      "PhISwap(0.25)─PhISwap(0.25)^0.5  Z^0              │\n",
      "│             │                  │                │\n",
      "Z^0           PhISwap(0.25)──────PhISwap(0.25)^-1 │\n",
      "│             │                  │                │\n",
      "│             Z^0                @────────────────@^0\n",
      "│             │                  │                │\n",
      "@─────────────@^0                ×────────────────×\n",
      "│             │                  │                │\n",
      "×─────────────×                  │                │\n",
      "│             │                  │                │\n",
      "│             @──────────────────@^0              │\n",
      "│             │                  │                │\n",
      "│             ×──────────────────×                │\n",
      "│             │                  │                │\n",
      "@─────────────@^0                @────────────────@^0\n",
      "│             │                  │                │\n",
      "×─────────────×                  ×────────────────×\n",
      "│             │                  │                │\n",
      "Rz(0)         @──────────────────@^0              Rz(0)\n",
      "│             │                  │                │\n",
      "Rz(0)         ×──────────────────×                Rz(0)\n",
      "│             │                  │                │\n",
      "Rz(0)         Rz(0)              Rz(0)            Rz(0)\n",
      "│             │                  │                │\n",
      "Rz(0.052π)    Rz(0)              Rz(0)            Rz(0.03π)\n",
      "│             │                  │                │\n",
      "Rz(0)         Rz(0)              Rz(0)            Rz(0)\n",
      "│             │                  │                │\n",
      "│             Rz(0.052π)         Rz(0.03π)        │\n",
      "│             │                  │                │\n",
      "│             Rz(0)              Rz(0)            │\n",
      "│             │                  │                │\n",
      "│             PhISwap(0.25)──────PhISwap(0.25)^-1 │\n",
      "│             │                  │                │\n",
      "PhISwap(0.25)─PhISwap(0.25)^-1   Z^0              │\n",
      "│             │                  │                │\n",
      "│             Z^0                PhISwap(0.25)────PhISwap(0.25)^-1\n",
      "│             │                  │                │\n",
      "│             PhISwap(0.25)──────PhISwap(0.25)^-1 Z^0\n",
      "│             │                  │                │\n",
      "@─────────────@^-0.022           Z^0              │\n",
      "│             │                  │                │\n",
      "×─────────────×                  @────────────────@^-0.021\n",
      "│             │                  │                │\n",
      "│             │                  ×────────────────×\n",
      "│             │                  │                │\n",
      "│             @──────────────────@^-0.021         │\n",
      "│             │                  │                │\n",
      "│             ×──────────────────×                │\n",
      "│             │                  │                │\n",
      "@─────────────@^-0.021           @────────────────@^-0.021\n",
      "│             │                  │                │\n",
      "×─────────────×                  ×────────────────×\n",
      "│             │                  │                │\n",
      "Rz(-0.01π)    @──────────────────@^-0.021         Rz(-0.011π)\n",
      "│             │                  │                │\n",
      "Rz(π)         ×──────────────────×                Rz(π)\n",
      "│             │                  │                │\n",
      "│             Rz(-0.01π)         Rz(-0.011π)      │\n",
      "│             │                  │                │\n",
      "│             Rz(0)              Rz(0)            │\n",
      "│             │                  │                │\n",
      "│             PhISwap(0.25)──────PhISwap(0.25)^-1 │\n",
      "│             │                  │                │\n",
      "│             Z^0                PhISwap(0.25)────PhISwap(0.25)^0.5\n",
      "│             │                  │                │\n",
      "PhISwap(0.25)─PhISwap(0.25)^-0.5 Z^0              │\n",
      "│             │                  │                │\n",
      "Z^0           PhISwap(0.25)──────PhISwap(0.25)^-1 │\n",
      "│             │                  │                │\n",
      "│             Z^0                @────────────────@^-0.006\n",
      "│             │                  │                │\n",
      "@─────────────@^-0.006           ×────────────────×\n",
      "│             │                  │                │\n",
      "×─────────────×                  │                │\n",
      "│             │                  │                │\n",
      "│             @──────────────────@^0.006          │\n",
      "│             │                  │                │\n",
      "│             ×──────────────────×                │\n",
      "│             │                  │                │\n",
      "@─────────────@^0.006            @────────────────@^0.006\n",
      "│             │                  │                │\n",
      "×─────────────×                  ×────────────────×\n",
      "│             │                  │                │\n",
      "Rz(-0.003π)   @──────────────────@^0.006          Rz(-0.003π)\n",
      "│             │                  │                │\n",
      "Rz(π)         ×──────────────────×                Rz(0)\n",
      "│             │                  │                │\n",
      "│             Rz(-0.003π)        Rz(-0.003π)      │\n",
      "│             │                  │                │\n",
      "│             Rz(0)              Rz(π)            │\n",
      "│             │                  │                │\n",
      "│             PhISwap(0.25)──────PhISwap(0.25)^-1 │\n",
      "│             │                  │                │\n",
      "PhISwap(0.25)─PhISwap(0.25)^-0.5 Z^0              │\n",
      "│             │                  │                │\n",
      "│             Z^0                PhISwap(0.25)────PhISwap(0.25)^0.5\n",
      "│             │                  │                │\n",
      "│             PhISwap(0.25)──────PhISwap(0.25)^-1 Z^0\n",
      "│             │                  │                │\n",
      "@─────────────@^0                Z^0              │\n",
      "│             │                  │                │\n",
      "×─────────────×                  @────────────────@^0\n",
      "│             │                  │                │\n",
      "│             │                  ×────────────────×\n",
      "│             │                  │                │\n",
      "│             @──────────────────@^0              │\n",
      "│             │                  │                │\n",
      "│             ×──────────────────×                │\n",
      "│             │                  │                │\n",
      "@─────────────@^0                @────────────────@^0\n",
      "│             │                  │                │\n",
      "×─────────────×                  ×────────────────×\n",
      "│             │                  │                │\n",
      "Rz(0)         @──────────────────@^0              Rz(0)\n",
      "│             │                  │                │\n",
      "Rz(0)         ×──────────────────×                Rz(0)\n",
      "│             │                  │                │\n",
      "Rz(0)         Rz(0)              Rz(0)            Rz(0)\n",
      "│             │                  │                │\n",
      "Rz(0.03π)     Rz(0)              Rz(0)            Rz(0.052π)\n",
      "│             │                  │                │\n",
      "Rz(0)         Rz(0)              Rz(0)            Rz(0)\n",
      "│             │                  │                │\n",
      "│             Rz(0.03π)          Rz(0.052π)       │\n",
      "│             │                  │                │\n",
      "│             Rz(0)              Rz(0)            │\n",
      "│             │                  │                │\n",
      "│             PhISwap(0.25)──────PhISwap(0.25)^-1 │\n",
      "│             │                  │                │\n",
      "│             Z^0                PhISwap(0.25)────PhISwap(0.25)^-1\n",
      "│             │                  │                │\n",
      "PhISwap(0.25)─PhISwap(0.25)^-1   Z^0              │\n",
      "│             │                  │                │\n",
      "Z^0           PhISwap(0.25)──────PhISwap(0.25)^-1 │\n",
      "│             │                  │                │\n",
      "│             Z^0                @────────────────@^-0.022\n",
      "│             │                  │                │\n",
      "@─────────────@^-0.021           ×────────────────×\n",
      "│             │                  │                │\n",
      "×─────────────×                  │                │\n",
      "│             │                  │                │\n",
      "│             @──────────────────@^-0.021         │\n",
      "│             │                  │                │\n",
      "│             ×──────────────────×                │\n",
      "│             │                  │                │\n",
      "@─────────────@^-0.021           @────────────────@^-0.021\n",
      "│             │                  │                │\n",
      "×─────────────×                  ×────────────────×\n",
      "│             │                  │                │\n",
      "Rz(-0.011π)   @──────────────────@^-0.021         Rz(-0.01π)\n",
      "│             │                  │                │\n",
      "Rz(π)         ×──────────────────×                Rz(π)\n",
      "│             │                  │                │\n",
      "│             Rz(-0.011π)        Rz(-0.01π)       │\n",
      "│             │                  │                │\n",
      "│             Rz(0)              Rz(0)            │\n",
      "│             │                  │                │\n",
      "│             PhISwap(0.25)──────PhISwap(0.25)^-1 │\n",
      "│             │                  │                │\n",
      "PhISwap(0.25)─PhISwap(0.25)^0.5  Z^0              │\n",
      "│             │                  │                │\n",
      "│             Z^0                PhISwap(0.25)────PhISwap(0.25)^-0.5\n",
      "│             │                  │                │\n",
      "│             PhISwap(0.25)──────PhISwap(0.25)^-1 Z^0\n",
      "│             │                  │                │\n",
      "@─────────────@^-0.006           Z^0              │\n",
      "│             │                  │                │\n",
      "×─────────────×                  @────────────────@^-0.006\n",
      "│             │                  │                │\n",
      "│             │                  ×────────────────×\n",
      "│             │                  │                │\n",
      "│             @──────────────────@^0.006          │\n",
      "│             │                  │                │\n",
      "│             ×──────────────────×                │\n",
      "│             │                  │                │\n",
      "@─────────────@^0.006            @────────────────@^0.006\n",
      "│             │                  │                │\n",
      "×─────────────×                  ×────────────────×\n",
      "│             │                  │                │\n",
      "Rz(-0.003π)   @──────────────────@^0.006          Rz(-0.003π)\n",
      "│             │                  │                │\n",
      "Rz(0)         ×──────────────────×                Rz(π)\n",
      "│             │                  │                │\n",
      "│             Rz(-0.003π)        Rz(-0.003π)      │\n",
      "│             │                  │                │\n",
      "│             Rz(π)              Rz(0)            │\n",
      "│             │                  │                │\n",
      "│             PhISwap(0.25)──────PhISwap(0.25)^-1 │\n",
      "│             │                  │                │\n",
      "│             Z^0                PhISwap(0.25)────PhISwap(0.25)^-0.5\n",
      "│             │                  │                │\n",
      "PhISwap(0.25)─PhISwap(0.25)^0.5  Z^0              │\n",
      "│             │                  │                │\n",
      "Z^0           PhISwap(0.25)──────PhISwap(0.25)^-1 │\n",
      "│             │                  │                │\n",
      "│             Z^0                @────────────────@^0\n",
      "│             │                  │                │\n",
      "@─────────────@^0                ×────────────────×\n",
      "│             │                  │                │\n",
      "×─────────────×                  │                │\n",
      "│             │                  │                │\n",
      "│             @──────────────────@^0              │\n",
      "│             │                  │                │\n",
      "│             ×──────────────────×                │\n",
      "│             │                  │                │\n",
      "@─────────────@^0                @────────────────@^0\n",
      "│             │                  │                │\n",
      "×─────────────×                  ×────────────────×\n",
      "│             │                  │                │\n",
      "Rz(0)         @──────────────────@^0              Rz(0)\n",
      "│             │                  │                │\n",
      "Rz(0)         ×──────────────────×                Rz(0)\n",
      "│             │                  │                │\n",
      "Rz(0)         Rz(0)              Rz(0)            Rz(0)\n",
      "│             │                  │                │\n",
      "Rz(0.052π)    Rz(0)              Rz(0)            Rz(0.03π)\n",
      "│             │                  │                │\n",
      "Rz(0)         Rz(0)              Rz(0)            Rz(0)\n",
      "│             │                  │                │\n",
      "│             Rz(0.052π)         Rz(0.03π)        │\n",
      "│             │                  │                │\n",
      "│             Rz(0)              Rz(0)            │\n",
      "│             │                  │                │\n",
      "│             PhISwap(0.25)──────PhISwap(0.25)^-1 │\n",
      "│             │                  │                │\n",
      "PhISwap(0.25)─PhISwap(0.25)^-1   Z^0              │\n",
      "│             │                  │                │\n",
      "│             Z^0                PhISwap(0.25)────PhISwap(0.25)^-1\n",
      "│             │                  │                │\n",
      "│             PhISwap(0.25)──────PhISwap(0.25)^-1 Z^0\n",
      "│             │                  │                │\n",
      "@─────────────@^-0.022           Z^0              │\n",
      "│             │                  │                │\n",
      "×─────────────×                  @────────────────@^-0.021\n",
      "│             │                  │                │\n",
      "│             │                  ×────────────────×\n",
      "│             │                  │                │\n",
      "│             @──────────────────@^-0.021         │\n",
      "│             │                  │                │\n",
      "│             ×──────────────────×                │\n",
      "│             │                  │                │\n",
      "@─────────────@^-0.021           @────────────────@^-0.021\n",
      "│             │                  │                │\n",
      "×─────────────×                  ×────────────────×\n",
      "│             │                  │                │\n",
      "Rz(-0.01π)    @──────────────────@^-0.021         Rz(-0.011π)\n",
      "│             │                  │                │\n",
      "Rz(π)         ×──────────────────×                Rz(π)\n",
      "│             │                  │                │\n",
      "│             Rz(-0.01π)         Rz(-0.011π)      │\n",
      "│             │                  │                │\n",
      "│             Rz(0)              Rz(0)            │\n",
      "│             │                  │                │\n",
      "│             PhISwap(0.25)──────PhISwap(0.25)^-1 │\n",
      "│             │                  │                │\n",
      "│             Z^0                PhISwap(0.25)────PhISwap(0.25)^0.5\n",
      "│             │                  │                │\n",
      "PhISwap(0.25)─PhISwap(0.25)^-0.5 Z^0              │\n",
      "│             │                  │                │\n",
      "Z^0           PhISwap(0.25)──────PhISwap(0.25)^-1 │\n",
      "│             │                  │                │\n",
      "│             Z^0                @────────────────@^-0.006\n",
      "│             │                  │                │\n",
      "@─────────────@^-0.006           ×────────────────×\n",
      "│             │                  │                │\n",
      "×─────────────×                  │                │\n",
      "│             │                  │                │\n",
      "│             @──────────────────@^0.006          │\n",
      "│             │                  │                │\n",
      "│             ×──────────────────×                │\n",
      "│             │                  │                │\n",
      "@─────────────@^0.006            @────────────────@^0.006\n",
      "│             │                  │                │\n",
      "×─────────────×                  ×────────────────×\n",
      "│             │                  │                │\n",
      "Rz(-0.003π)   @──────────────────@^0.006          Rz(-0.003π)\n",
      "│             │                  │                │\n",
      "Rz(π)         ×──────────────────×                Rz(0)\n",
      "│             │                  │                │\n",
      "│             Rz(-0.003π)        Rz(-0.003π)      │\n",
      "│             │                  │                │\n",
      "│             Rz(0)              Rz(π)            │\n",
      "│             │                  │                │\n",
      "│             PhISwap(0.25)──────PhISwap(0.25)^-1 │\n",
      "│             │                  │                │\n",
      "PhISwap(0.25)─PhISwap(0.25)^-0.5 Z^0              │\n",
      "│             │                  │                │\n",
      "│             Z^0                PhISwap(0.25)────PhISwap(0.25)^0.5\n",
      "│             │                  │                │\n",
      "│             PhISwap(0.25)──────PhISwap(0.25)^-1 Z^0\n",
      "│             │                  │                │\n",
      "@─────────────@^0                Z^0              │\n",
      "│             │                  │                │\n",
      "×─────────────×                  @────────────────@^0\n",
      "│             │                  │                │\n",
      "│             │                  ×────────────────×\n",
      "│             │                  │                │\n",
      "│             @──────────────────@^0              │\n",
      "│             │                  │                │\n",
      "│             ×──────────────────×                │\n",
      "│             │                  │                │\n",
      "@─────────────@^0                @────────────────@^0\n",
      "│             │                  │                │\n",
      "×─────────────×                  ×────────────────×\n",
      "│             │                  │                │\n",
      "Rz(0)         @──────────────────@^0              Rz(0)\n",
      "│             │                  │                │\n",
      "Rz(0)         ×──────────────────×                Rz(0)\n",
      "│             │                  │                │\n",
      "Rz(0)         Rz(0)              Rz(0)            Rz(0)\n",
      "│             │                  │                │\n",
      "Rz(0.03π)     Rz(0)              Rz(0)            Rz(0.052π)\n",
      "│             │                  │                │\n",
      "Rz(0)         Rz(0)              Rz(0)            Rz(0)\n",
      "│             │                  │                │\n",
      "│             Rz(0.03π)          Rz(0.052π)       │\n",
      "│             │                  │                │\n",
      "│             Rz(0)              Rz(0)            │\n",
      "│             │                  │                │\n",
      "│             PhISwap(0.25)──────PhISwap(0.25)^-1 │\n",
      "│             │                  │                │\n",
      "│             Z^0                PhISwap(0.25)────PhISwap(0.25)^-1\n",
      "│             │                  │                │\n",
      "PhISwap(0.25)─PhISwap(0.25)^-1   Z^0              │\n",
      "│             │                  │                │\n",
      "Z^0           PhISwap(0.25)──────PhISwap(0.25)^-1 │\n",
      "│             │                  │                │\n",
      "│             Z^0                @────────────────@^-0.022\n",
      "│             │                  │                │\n",
      "@─────────────@^-0.021           ×────────────────×\n",
      "│             │                  │                │\n",
      "×─────────────×                  │                │\n",
      "│             │                  │                │\n",
      "│             @──────────────────@^-0.021         │\n",
      "│             │                  │                │\n",
      "│             ×──────────────────×                │\n",
      "│             │                  │                │\n",
      "@─────────────@^-0.021           @────────────────@^-0.021\n",
      "│             │                  │                │\n",
      "×─────────────×                  ×────────────────×\n",
      "│             │                  │                │\n",
      "Rz(-0.011π)   @──────────────────@^-0.021         Rz(-0.01π)\n",
      "│             │                  │                │\n",
      "Rz(π)         ×──────────────────×                Rz(π)\n",
      "│             │                  │                │\n",
      "│             Rz(-0.011π)        Rz(-0.01π)       │\n",
      "│             │                  │                │\n",
      "│             Rz(0)              Rz(0)            │\n",
      "│             │                  │                │\n",
      "│             PhISwap(0.25)──────PhISwap(0.25)^-1 │\n",
      "│             │                  │                │\n",
      "PhISwap(0.25)─PhISwap(0.25)^0.5  Z^0              │\n",
      "│             │                  │                │\n",
      "│             Z^0                PhISwap(0.25)────PhISwap(0.25)^-0.5\n",
      "│             │                  │                │\n",
      "│             PhISwap(0.25)──────PhISwap(0.25)^-1 Z^0\n",
      "│             │                  │                │\n",
      "@─────────────@^-0.006           Z^0              │\n",
      "│             │                  │                │\n",
      "×─────────────×                  @────────────────@^-0.006\n",
      "│             │                  │                │\n",
      "│             │                  ×────────────────×\n",
      "│             │                  │                │\n",
      "│             @──────────────────@^0.006          │\n",
      "│             │                  │                │\n",
      "│             ×──────────────────×                │\n",
      "│             │                  │                │\n",
      "@─────────────@^0.006            @────────────────@^0.006\n",
      "│             │                  │                │\n",
      "×─────────────×                  ×────────────────×\n",
      "│             │                  │                │\n",
      "Rz(-0.003π)   @──────────────────@^0.006          Rz(-0.003π)\n",
      "│             │                  │                │\n",
      "Rz(0)         ×──────────────────×                Rz(π)\n",
      "│             │                  │                │\n",
      "│             Rz(-0.003π)        Rz(-0.003π)      │\n",
      "│             │                  │                │\n",
      "│             Rz(π)              Rz(0)            │\n",
      "│             │                  │                │\n",
      "│             PhISwap(0.25)──────PhISwap(0.25)^-1 │\n",
      "│             │                  │                │\n",
      "│             Z^0                PhISwap(0.25)────PhISwap(0.25)^-0.5\n",
      "│             │                  │                │\n",
      "PhISwap(0.25)─PhISwap(0.25)^0.5  Z^0              │\n",
      "│             │                  │                │\n",
      "Z^0           PhISwap(0.25)──────PhISwap(0.25)^-1 │\n",
      "│             │                  │                │\n",
      "│             Z^0                @────────────────@^0\n",
      "│             │                  │                │\n",
      "@─────────────@^0                ×────────────────×\n",
      "│             │                  │                │\n",
      "×─────────────×                  │                │\n",
      "│             │                  │                │\n",
      "│             @──────────────────@^0              │\n",
      "│             │                  │                │\n",
      "│             ×──────────────────×                │\n",
      "│             │                  │                │\n",
      "@─────────────@^0                @────────────────@^0\n",
      "│             │                  │                │\n",
      "×─────────────×                  ×────────────────×\n",
      "│             │                  │                │\n",
      "Rz(0)         @──────────────────@^0              Rz(0)\n",
      "│             │                  │                │\n",
      "Rz(0)         ×──────────────────×                Rz(0)\n",
      "│             │                  │                │\n",
      "│             Rz(0)              Rz(0)            │\n",
      "│             │                  │                │\n",
      "│             Rz(0)              Rz(0)            │\n",
      "│             │                  │                │\n"
     ]
    }
   ],
   "source": [
    "print(circuit.to_text_diagram(transpose=True))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "vim-c2VhuGZO"
   },
   "source": [
    "## Bogoliubov transformation\n",
    "\n",
    "- Single-particle orbital basis change\n",
    "- In the particle-conserving case, takes the form\n",
    "$$\n",
    "U a_p^\\dagger U^\\dagger = b_p^\\dagger, \\quad b_p^\\dagger = \\sum_{q} u_{pq} a_q^\\dagger\n",
    "$$\n",
    "and $u$ is unitary.\n",
    "- Can be used to diagonalize any quadratic Hamiltonian:\n",
    "$$\n",
    "\\sum_{p, q} T_{pq} a_p^\\dagger a_q \\mapsto \\sum_{j} \\varepsilon_j b_j^\\dagger b_j + \\text{constant}\n",
    "$$\n",
    "- Implementation from [arXiv:1711.05395](https://arxiv.org/pdf/1711.05395.pdf); uses linear depth and linear connectivity\n",
    "\n",
    "As an example, we'll prepare the ground state of a random particle-conserving quadratic Hamiltonian."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "metadata": {
    "id": "sOhY4QQtuGZP"
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "1.690525703800356 [] +\n",
      "(0.5315776978980016+0j) [0^ 0] +\n",
      "(-1.347208023348913+2.7004721387490935j) [0^ 1] +\n",
      "(-0.28362365442898696-1.8784499457335426j) [0^ 2] +\n",
      "(0.12594647819298657-1.3106154125325498j) [0^ 3] +\n",
      "(-0.3880303291443195-1.1751249212322041j) [0^ 4] +\n",
      "(-1.347208023348913-2.7004721387490935j) [1^ 0] +\n",
      "(2.5012533818678193+0j) [1^ 1] +\n",
      "(0.3391421007279024-3.8305756810505094j) [1^ 2] +\n",
      "(-0.3509690502067961+0.090677856754656j) [1^ 3] +\n",
      "(1.8575239595653907-1.4736314761076197j) [1^ 4] +\n",
      "(-0.28362365442898696+1.8784499457335426j) [2^ 0] +\n",
      "(0.3391421007279024+3.8305756810505094j) [2^ 1] +\n",
      "(-0.019560786804260433+0j) [2^ 2] +\n",
      "(-2.979765944360631+2.5490724453105917j) [2^ 3] +\n",
      "(0.5091942820312417+0.344618218148502j) [2^ 4] +\n",
      "(0.12594647819298657+1.3106154125325498j) [3^ 0] +\n",
      "(-0.3509690502067961-0.090677856754656j) [3^ 1] +\n",
      "(-2.979765944360631-2.5490724453105917j) [3^ 2] +\n",
      "(3.767336752913784+0j) [3^ 3] +\n",
      "(-1.2963431636902167-1.5288970105744286j) [3^ 4] +\n",
      "(-0.3880303291443195+1.1751249212322041j) [4^ 0] +\n",
      "(1.8575239595653907+1.4736314761076197j) [4^ 1] +\n",
      "(0.5091942820312417-0.344618218148502j) [4^ 2] +\n",
      "(-1.2963431636902167+1.5288970105744286j) [4^ 3] +\n",
      "(-0.3445183403145406+0j) [4^ 4]\n"
     ]
    }
   ],
   "source": [
    "n_qubits = 5\n",
    "quad_ham = of.random_quadratic_hamiltonian(\n",
    "    n_qubits, conserves_particle_number=True, seed=7\n",
    ")\n",
    "\n",
    "print(of.get_fermion_operator(quad_ham))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "HwObrpO5uGZS"
   },
   "source": [
    "Now we construct a circuit which maps computational basis states to eigenstates of the Hamiltonian."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "metadata": {
    "id": "P1w7kKokuGZT"
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "0             1                   2                    3                     4\n",
      "│             │                   │                    │                     │\n",
      "Rz(0)         Rz(0)               Rz(π)                Rz(-π)                Rz(0)\n",
      "│             │                   │                    │                     │\n",
      "│             │                   │                    PhISwap(0.25)─────────PhISwap(0.25)^0.073\n",
      "│             │                   │                    │                     │\n",
      "│             │                   PhISwap(0.25)────────PhISwap(0.25)^(5/11)  Z^(-7/9)\n",
      "│             │                   │                    │                     │\n",
      "│             PhISwap(0.25)───────PhISwap(0.25)^0.814  Z^-0.508              │\n",
      "│             │                   │                    │                     │\n",
      "PhISwap(0.25)─PhISwap(0.25)^0.703 Z^-0.304             PhISwap(0.25)─────────PhISwap(0.25)^0.381\n",
      "│             │                   │                    │                     │\n",
      "│             Z^-0.767            PhISwap(0.25)────────PhISwap(0.25)^(13/16) Z^0.401\n",
      "│             │                   │                    │                     │\n",
      "│             PhISwap(0.25)───────PhISwap(0.25)^(7/11) Z^(-13/14)            │\n",
      "│             │                   │                    │                     │\n",
      "│             │                   Z^0.393              PhISwap(0.25)─────────PhISwap(0.25)^0.481\n",
      "│             │                   │                    │                     │\n",
      "│             │                   PhISwap(0.25)────────PhISwap(0.25)^0.422   Z^-0.738\n",
      "│             │                   │                    │                     │\n",
      "│             │                   │                    Z^-0.824              │\n",
      "│             │                   │                    │                     │\n",
      "│             │                   │                    PhISwap(0.25)─────────PhISwap(0.25)^0.506\n",
      "│             │                   │                    │                     │\n",
      "│             │                   │                    │                     Z^(5/7)\n",
      "│             │                   │                    │                     │\n"
     ]
    }
   ],
   "source": [
    "_, basis_change_matrix, _ = quad_ham.diagonalizing_bogoliubov_transform()\n",
    "\n",
    "qubits = cirq.LineQubit.range(n_qubits)\n",
    "circuit = cirq.Circuit(of.bogoliubov_transform(qubits, basis_change_matrix))\n",
    "\n",
    "print(circuit.to_text_diagram(transpose=True))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "-jDHy5izuGZV"
   },
   "source": [
    "In the rotated basis, the quadratic Hamiltonian takes the form\n",
    "$$\n",
    "H = \\sum_j \\varepsilon_j b_j^\\dagger b_j + \\text{constant}\n",
    "$$\n",
    "We can get the $\\varepsilon_j$ and the constant using the `orbital_energies` method of `QuadraticHamiltonian`."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 21,
   "metadata": {
    "id": "Q0aZhjc0uGZW"
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[-6.25377614 -1.2291963   0.71202361  5.0062515   8.20078604]\n",
      "1.690525703800356\n"
     ]
    }
   ],
   "source": [
    "orbital_energies, constant = quad_ham.orbital_energies()\n",
    "\n",
    "print(orbital_energies)\n",
    "print(constant)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "YCsxdHRpuGZZ"
   },
   "source": [
    "The ground state of the Hamiltonian is prepared by filling in the orbitals with negative energy."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "metadata": {
    "id": "ggOZq0DXuGZZ"
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "(-5.792446738060052+1.1102230246251565e-16j)\n",
      "-5.792446738060049\n"
     ]
    }
   ],
   "source": [
    "# Apply the circuit with initial state having the first two modes occupied.\n",
    "result = circuit.final_state_vector(initial_state=0b11000)\n",
    "\n",
    "# Compute the expectation value of the final state with the Hamiltonian\n",
    "quad_ham_sparse = of.get_sparse_operator(quad_ham)\n",
    "print(of.expectation(quad_ham_sparse, result))\n",
    "\n",
    "# Print out the ground state energy; it should match\n",
    "print(quad_ham.ground_energy())"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "6WXdbSBmuGZc"
   },
   "source": [
    "Recall that the Jordan-Wigner transform of $b_j^\\dagger b_j$ is $\\frac12(I-Z)$. Therefore, $\\exp(-i \\varepsilon_j b_j^\\dagger b_j)$ is equivalent to a single-qubit Z rotation under the JWT. Since the operators $b_j^\\dagger b_j$ commute, we have\n",
    "$$\n",
    "\\exp(-i H t) = \\exp(-i \\sum_j \\varepsilon_j b_j^\\dagger b_j t)\n",
    "= \\prod_j \\exp(-i \\varepsilon_j b_j^\\dagger b_j t)\n",
    "$$\n",
    "This gives a method for simulating time evolution under a quadratic Hamiltonian:\n",
    "- Use a Bogoliubov transformation to change to the basis in which the Hamiltonian is diagonal (Note: this transformation might be the inverse of what you expect. In that case, use `cirq.inverse`)\n",
    "- Apply single-qubit Z-rotations with angles proportional to the orbital energies\n",
    "- Undo the basis change\n",
    "\n",
    "The code cell below creates a random initial state and applies time evolution by direct matrix exponentiation."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 23,
   "metadata": {
    "id": "pqELuMY8uGZd"
   },
   "outputs": [],
   "source": [
    "# Create a random initial state\n",
    "initial_state = of.haar_random_vector(2**n_qubits)\n",
    "\n",
    "# Set evolution time\n",
    "time = 1.0\n",
    "\n",
    "# Apply exp(-i H t) to the state\n",
    "final_state = linalg.expm_multiply(-1j * quad_ham_sparse * time, initial_state)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "dFzXiKp0uGZf"
   },
   "source": [
    "### Exercise\n",
    "\n",
    "Fill in the code cell below to construct a circuit which applies $\\exp(-i H t)$ using the method described above"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 24,
   "metadata": {
    "id": "f0y43UhbuGZh"
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "0.08926042490120051\n"
     ]
    }
   ],
   "source": [
    "# Initialize qubits\n",
    "qubits = cirq.LineQubit.range(n_qubits)\n",
    "\n",
    "# Write code below to create the circuit\n",
    "# You should define the `circuit` variable here\n",
    "# ---------------------------------------------\n",
    "\n",
    "\n",
    "# ---------------------------------------------\n",
    "\n",
    "# Apply the circuit to the initial state\n",
    "result = circuit.final_state_vector(initial_state)\n",
    "\n",
    "# Compute the fidelity with the correct final state\n",
    "fidelity = abs(np.dot(final_state, result.conj())) ** 2\n",
    "\n",
    "# Print fidelity; it should be 1\n",
    "print(fidelity)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "Wp1a_Zf8EUen"
   },
   "source": [
    "### Solution"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 25,
   "metadata": {
    "id": "QHQvLlf1uGZt"
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "0.999999999999994\n"
     ]
    }
   ],
   "source": [
    "# Initialize qubits\n",
    "qubits = cirq.LineQubit.range(n_qubits)\n",
    "\n",
    "# Write code below to create the circuit\n",
    "# You should define the `circuit` variable here\n",
    "# ---------------------------------------------\n",
    "def exponentiate_quad_ham(qubits, quad_ham):\n",
    "    _, basis_change_matrix, _ = quad_ham.diagonalizing_bogoliubov_transform()\n",
    "    orbital_energies, _ = quad_ham.orbital_energies()\n",
    "\n",
    "    yield cirq.inverse(of.bogoliubov_transform(qubits, basis_change_matrix))\n",
    "    for i in range(len(qubits)):\n",
    "        yield cirq.rz(rads=-orbital_energies[i]).on(qubits[i])\n",
    "    yield of.bogoliubov_transform(qubits, basis_change_matrix)\n",
    "\n",
    "\n",
    "circuit = cirq.Circuit(exponentiate_quad_ham(qubits, quad_ham))\n",
    "# ---------------------------------------------\n",
    "\n",
    "# Apply the circuit to the initial state\n",
    "result = circuit.final_state_vector(initial_state)\n",
    "\n",
    "# Compute the fidelity with the correct final state\n",
    "fidelity = abs(np.dot(final_state, result.conj())) ** 2\n",
    "\n",
    "# Print fidelity; it should be 1\n",
    "print(fidelity)"
   ]
  }
 ],
 "metadata": {
  "colab": {
   "collapsed_sections": [
    "Wp1a_Zf8EUen"
   ],
   "name": "chemistry.ipynb",
   "toc_visible": true
  },
  "kernelspec": {
   "display_name": "Python 3",
   "name": "python3"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 0
}
